package com.hanter.android.radwidget.cupertino;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;

import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatEditText;

import com.etoonet.android.radwidget.R;

/**
 * 类名：MyEditText <br/>
 * 描述：Drawable可点击的EditText
 * 创建时间：2019/10/07 11:07
 *
 * @author hanter
 * @version 1.0
 */
public class SearchBar extends AppCompatEditText {

    private static final String TAG = "SearchBar";

    public static final int IN_BOUND_LEFT = 0;
    public static final int IN_BOUND_TOP = 1;
    public static final int IN_BOUND_RIGHT = 2;
    public static final int IN_BOUND_BOTTOM = 3;
    public static final int IN_BOUND_NONE = 4;

    private boolean mShowLeft;
    private int mDragged;
    int[] mLocation = new int[2];

    @Nullable
    private OnDrawableClickListener mOnDrawableClickListener;
    private boolean pressSearch;

    public interface OnDrawableClickListener {
        void onDrawableClickListener(int dragged);
    }

    public SearchBar(Context context) {
        this(context, null);
    }

    public SearchBar(Context context, AttributeSet attrs) {
        this(context, attrs, R.attr.editTextStyle);
    }

    public SearchBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        setSingleLine(true);
        setMaxLines(1);
        setImeOptions(EditorInfo.IME_ACTION_SEARCH);
        setCompoundDrawablesWithIntrinsicBounds(R.mipmap.ic_search_bar_search, 0,
                R.mipmap.ic_search_bar_clear, 0);
    }

    @Override
    protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
        super.onFocusChanged(focused, direction, previouslyFocusedRect);

        if (!pressSearch && (getText() == null || getText().toString().isEmpty())) {
            mShowLeft = focused;
        }

    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        pressSearch = (event.getKeyCode() == KeyEvent.KEYCODE_ENTER);
        if (pressSearch) {
            hideSoftInput();
        }
        return super.dispatchKeyEvent(event);
    }

    private void hideSoftInput() {
        InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
        if (imm != null && imm.isActive()) {
            imm.hideSoftInputFromWindow(getApplicationWindowToken(), 0);
            getApplicationWindowToken();
        }
    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        final int action = event.getActionMasked();

        boolean handled = false;

        switch (action) {
            case MotionEvent.ACTION_DOWN: {
                int dragged = isInBounds(event);
                if (mShowLeft) {
                    mDragged = dragged;
                } else {
                    mDragged = IN_BOUND_NONE;
                }
                handled = mDragged != IN_BOUND_NONE;
                break;
            }

            case MotionEvent.ACTION_UP:
                int dragged = isInBounds(event);
                if (dragged != IN_BOUND_NONE && dragged == mDragged && mOnDrawableClickListener != null) {
                    handled = true;

                    // clear text
                    if (dragged == IN_BOUND_RIGHT && getText() != null) {
                        getText().clear();
                    }

                    mOnDrawableClickListener.onDrawableClickListener(dragged);
                }
                mDragged = IN_BOUND_NONE;
                break;

            case MotionEvent.ACTION_CANCEL:
                if (mDragged != IN_BOUND_NONE) {
                    handled = true;
                }

                mDragged = IN_BOUND_NONE;
                break;
        }

        if (handled) {
            return true;
        } else {
            return super.onTouchEvent(event);
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (mShowLeft) {
            super.onDraw(canvas);
        } else {
            Drawable[] drawables = getCompoundDrawables();
            Drawable drawableLeft = drawables[0];
            if (drawableLeft != null) {
                float textWidth = getPaint().measureText(getHint().toString());
                int drawablePadding = getCompoundDrawablePadding();
                int drawableWidth = drawableLeft.getIntrinsicWidth();
                float bodyWidth = textWidth + drawableWidth + drawablePadding;
                canvas.translate((getWidth() - bodyWidth - getPaddingLeft() - getPaddingRight()) / 2, 0);
            }
            super.onDraw(canvas);
        }
    }


    private int isInBounds(MotionEvent event) {
        int rawX = (int) (event.getRawX() + 0.5f);
        int rawY = (int) (event.getRawY() + 0.5f);
        Drawable[] drawables = getCompoundDrawables();

        int index = IN_BOUND_LEFT;
        while (index < IN_BOUND_NONE) {
            int result = isInBounds(index, rawX, rawY);
            if (result != IN_BOUND_NONE) {
                return result;
            }
            index++;
        }
        return IN_BOUND_NONE;
    }

    private int isInBounds(int orientation, int rawX, int rawY) {
        Rect rect = getDrawableRect(orientation);
        if (rect != null) {
            getLocationOnScreen(mLocation);
            rect.offset(mLocation[0], mLocation[1]);
            return rect.contains(rawX, rawY) ? orientation : IN_BOUND_NONE;
        }
        return IN_BOUND_NONE;
    }

    private Rect getDrawableRect(int orientation) {
        Drawable[] drawables = getCompoundDrawables();

        switch (orientation) {
            case IN_BOUND_LEFT:

                if (drawables[IN_BOUND_LEFT] == null)
                    return null;

                return new Rect(getPaddingLeft(), getPaddingTop(),
                        getPaddingLeft() + drawables[IN_BOUND_LEFT].getBounds().width(), getBottom() - getTop() - getPaddingBottom());

            case IN_BOUND_RIGHT:

                if (drawables[IN_BOUND_RIGHT] == null)
                    return null;

                return new Rect(getRight() - getLeft() - getPaddingRight() - drawables[IN_BOUND_RIGHT].getBounds().width(), getPaddingTop(),
                        getRight() - getLeft() - getPaddingRight(), getBottom() - getTop() - getPaddingBottom());

            case IN_BOUND_TOP:

                if (drawables[IN_BOUND_TOP] == null)
                    return null;

                return new Rect(getPaddingLeft(), getPaddingTop(),
                        getRight() - getLeft() - getPaddingRight(), getPaddingTop() + drawables[IN_BOUND_TOP].getBounds().width());

            case IN_BOUND_BOTTOM:

                if (drawables[IN_BOUND_BOTTOM] == null)
                    return null;

                return new Rect(getPaddingLeft(), getBottom() - getTop() - getPaddingBottom() - drawables[IN_BOUND_BOTTOM].getBounds().width(),
                        getRight() - getLeft() - getPaddingRight(), getBottom() - getTop() - getPaddingBottom());

            default:
                return null;
        }
    }

    @Nullable
    public OnDrawableClickListener getOnDrawableClickListener() {
        return mOnDrawableClickListener;
    }

    public void setOnDrawableClickListener(@Nullable OnDrawableClickListener onDrawableClickListener) {
        this.mOnDrawableClickListener = onDrawableClickListener;
    }
}
